/**
 * A class which represents a holiday for a driver.
 * A holiday has a start date, a duration of a number of days,
 * and belongs to a particular driver, given by the driverID.
 * A holiday cannot be given if more than MAX_NO_PEOPLE
 * are currently on holiday during the set time
 * frame, or if a driver has had more than their HOLIDAYS_PER_YEAR.
 *
 * Updated - Now takes into account that Sunday can have more people
 * off, i.e MAX_NO_PEOPLE_SUNDAY can be off at one time on sunday.
 * 
 * @version 1.1
 */

import java.util.Date;
import java.util.Calendar;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;

public class Holiday
{
    //The maximum number of people who can be on holiday at one time(weekdays)
    private static final int MAX_NO_PEOPLE_WEEKDAY = 10;
    //The amount of people allowed off today, used for the iteration loop
    private static int MAX_NO_PEOPLE = 10;
    //The number of people on holiday at Sunday
    private static final int MAX_NO_PEOPLE_SUNDAY = 25;
    //The maximum number of days a driver can be on holiday a year
    private static int HOLIDAYS_PER_YEAR = 25;


    //The start date of the holiday
    private Date startDate;
    //The duration of the holiday in days
    private int noDays;
    //The ID of the driver who requests the holiday
    private int driverID;
    //Whether an Error GUI should popup to show failure reasoning, true
    //by default
    private boolean isErrorGUI = true;
    //The current year
    private int year;

    /**
     * Constructor, takes a String representing a start date in the format
     * "DD-MMM-YY", e.g Feb 22, 2012, the number of days duration and the
     * driver ID of whom requested the holiday
     *
     * @param startDate The start date of the requested holiday in String format
     * @param noDays The duration of the holiday from the start date
     * @param driverID The id of the driver who requested the holiday
     *
     * @throws ParseException if cannot parse given date
     */
    public Holiday(String startDate,
                   int noDays,
                   int driverID) throws ParseException
    {
        //Parse the date from string to Date object
        DateFormat formatter = new SimpleDateFormat("MMM dd, yyyy");

        this.startDate = (Date)formatter.parse(startDate);
        this.noDays = noDays;
        this.driverID = driverID;
        //Set the current year
        this.year = Calendar.getInstance().get(Calendar.YEAR);
    }
 	
    /**
    * Constructor, takes a 'Date' object as the date, and thus does
    * not need any parsing.
    *
    * @param startDate The start date of the requested holiday in Date format
    * @param noDays The duration of the holiday from the start date
    * @param driverID The id of the driver who requested the holiday
    *
    */
    public Holiday(Date startDate,
                   int noDays,
                   int driverID)
    {
        this.startDate = startDate;
        this.noDays = noDays;
        this.driverID = driverID;
        //Set the current year
        this.year = Calendar.getInstance().get(Calendar.YEAR);
    }

    /**
    * Constructor, sets the date of holiday to today.
    *
    * @param noDays The duration of the holiday from the start date
    * @param driverID The id of the driver who requested the holiday
    *
    */
    public Holiday(int noDays,
                   int driverID)
    {
        this.startDate = new Date();
        this.noDays = noDays;
        this.driverID = driverID;
        //Sets the current year
        this.year = Calendar.getInstance().get(Calendar.YEAR);
    }


     /**
      * Decides whether Error Gui popups should happen to display
      * reasoning behind errors. This is true by default.
      *
      * @param shouldShow Whether the error popup should show, true for should
      * show false otherwise
      */
     public void showError(boolean shouldShow)
     {
        this.isErrorGUI = shouldShow;
     }

     private static void setMaxNoPeople(int newMax)
    {
         MAX_NO_PEOPLE = newMax;
    }
     //Set the number of holidays per year. This can be used if
     //a driver goes over a new year in terms of holidays
     private static void setHolidays(int newHolidays)
     {
         HOLIDAYS_PER_YEAR = newHolidays;
     }


    /**
     * Attempts to set a holiday in the given timeframe for the
     * driver who the Holidays's ID belongs to.
     *
     * @returns true if holiday was set, false if failure
     */

    public boolean setHoliday()
    {
        //First check if this employee has requested too many holidays,
        //or will request too many holidays
        if ((DriverInfo.getHolidaysTaken(this.driverID) + this.noDays) > HOLIDAYS_PER_YEAR)
        {
            if (isErrorGUI)
                    ErrorGui.showError("Error",
                                        "You have already requested more than "
                                        + "your quota of holidays");
            return false;
        }

        //Check if holiday will go beyond the new year
        //Calculate end date
        Calendar cal = Calendar.getInstance();



        int holidayCount = 0; //The number of people on holiday at one time
        //The IDs of all drivers in the database
        int[] driverIDs = DriverInfo.getDrivers();

        cal.setTime(this.startDate);

        for (int day = 0; day < this.noDays; day++)
        {
            for (int driver = 0; driver < driverIDs.length; driver++)
            {
                //If sunday, 25(?) people can be off at one time
                if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
                    setHolidays(MAX_NO_PEOPLE_SUNDAY);
                else
                    setHolidays(MAX_NO_PEOPLE_WEEKDAY);

                if (!DriverInfo.isAvailable(driverIDs[driver], cal.getTime()))
                {
                    holidayCount++;
                }
            }
            if (holidayCount >= MAX_NO_PEOPLE)
            {
                if (isErrorGUI)
                    ErrorGui.showError("Error",
                                       "Too many people are on holiday in this period");
                return false;
            }
            System.out.println("Date: " + cal.getTime() + "Holiday Count: " + holidayCount);
            //Increment date
            cal.add(Calendar.DATE, 1);
            holidayCount = 0;
        }

        //If we get through the loop, we are OK!
        //Therefore, set the holiday for the driver
        cal.setTime(this.startDate);

        int howManyDays = 0;
        for (int day = 0; day < this.noDays; day++)
        {
            if (DriverInfo.isAvailable(this.driverID, cal.getTime()))
            {
                DriverInfo.setAvailable(this.driverID, cal.getTime(), false);
                howManyDays++;
            }
                cal.add(Calendar.DATE, 1);
        }

        //Set holidays taken this year
        int currentHolidays = DriverInfo.getHolidaysTaken(this.driverID);
        int newHoliday = currentHolidays + howManyDays;
        //System.out.println("Current holidays : " + currentHolidays + "how many days: " + howManyDays + "new Holiday: " + newHoliday);
        DriverInfo.setHolidaysTaken(this.driverID, newHoliday);

        
        return true;

    }

    public int calculateDaysLeft()
    {
        return HOLIDAYS_PER_YEAR - (DriverInfo.getHolidaysTaken(this.driverID));
    }
    public static void main(String[] args)
    {
        database.openBusDatabase();
        int id = 2019;
        System.out.println("Holidays taken: " + DriverInfo.getHolidaysTaken(id));
        String date = "1-Mar-12";
        int noDays = 5;


        try
        {
            //Holiday h = new Holiday(date, noDays, id);
            Holiday h2 = new Holiday("Feb 22, 2012", 10, 2019);
            //System.out.println("Result: "  + h.setHoliday());
            h2.setHoliday();
        }
        catch (ParseException e)
        {

        }

        System.out.println("Holidays taken: " + DriverInfo.getHolidaysTaken(id));
    }
}
